package microcredit.model;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import microcredit.model.base.Model;
import microcredit.model.util.ModelUtils;

@Entity
public class MemberToLoanEntry extends Model {

	@Id
	@Column(name="MEMBER_ID", updatable=false, insertable=false)
	private Long memberID;
	
	@Id
	@Column(name="SEQUENCE_ID", updatable=false, insertable=false)
	private Long loanSequenceID;
	
	@Id
	@Column(name="ENTRYSEQUENCE_ID")
	private Long entrySequenceID;
	
	@Column(nullable=false)
	private BigDecimal amount;
	
	@Column()
	private BigDecimal amountPaid;
	
	@Column
	private Boolean fixed;
	
	@Column
	private Boolean locked;
	
	@Column
	private Boolean securityPaid;
	
	@Temporal(TemporalType.DATE)
	@Column(nullable=false)
	private Date startDate;
	@Temporal(TemporalType.DATE)
	@Column(nullable=false)
	private Date endDate;
	
	@Temporal(TemporalType.TIMESTAMP)
	@Column(nullable=false)
	private Date insertStamp;
	
	@Temporal(TemporalType.TIMESTAMP)
	@Column(nullable=false)
	private Date updateStamp;

	@OneToOne()
	private MemberToLoan memberToLoan;
	
	public MemberToLoanEntry() {
	}
	
	public void setSecurityPaid(Boolean securityPaid) {
		this.securityPaid = securityPaid;
	}
	
	public Boolean getSecurityPaid() {
		return securityPaid;
	}
	
	@PrePersist
	public void prePersist() throws ValidationException {
		if (getInsertStamp() == null) {
			setInsertStamp(ModelUtils.createTimestamp());
		}
		setUpdateStamp(getInsertStamp());
		validate();
	}
	
	@PreUpdate
	public void preUpdate() throws ValidationException {
		setUpdateStamp(ModelUtils.createTimestamp());
		validate();
	}
	
	public void validate() throws ValidationException {
		//TODO a lot more validations necessary
	}
	
	public Boolean getLocked() {
		return locked;
	}
	
	public void setLocked(Boolean locked) {
		this.locked = locked;
	}
	
	public Date getStartDate() {
		return startDate;
	}

	public void setStartDate(Date startDate) {
		this.startDate = startDate;
	}

	public Date getEndDate() {
		return endDate;
	}

	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}

	public Boolean getFixed() {
		return fixed;
	}

	public void setFixed(Boolean exact) {
		Boolean oldFixed = this.fixed;
		this.fixed = exact;
		firePropertyChange("fixed", oldFixed, fixed);
		if (fixed != null && fixed.booleanValue()
				&& getAmountPaid() == null) {
			setAmountPaid(new BigDecimal(0));
		}
	}

	public Date getUpdateStamp() {
		return updateStamp;
	}

	public void setUpdateStamp(Date updateStamp) {
		Object oldupdateStamp = this.updateStamp;
		this.updateStamp = updateStamp;
		firePropertyChange("updateStamp", oldupdateStamp, this.updateStamp);
	}

	public MemberToLoan getMemberToLoan() {
		return memberToLoan;
	}

	public void setMemberToLoan(MemberToLoan memberToLoan) {
		Object oldmemberToLoan = this.memberToLoan;
		this.memberToLoan = memberToLoan;
		firePropertyChange("memberToLoan", oldmemberToLoan, this.memberToLoan);
	}

	public Long getMemberID() {
		return memberID;
	}

	public BigDecimal getAmountPaid() {
		return amountPaid;
	}

	public void setAmountPaid(BigDecimal amountPaid) {
		Object oldamountPaid = this.amountPaid;
		this.amountPaid = amountPaid;
		firePropertyChange("amountPaid", oldamountPaid, this.amountPaid);
		if (amountPaid == null) {
			setFixed(false);
		}
	}

	public void setMemberID(Long memberID) {
		Object oldmemberID = this.memberID;
		this.memberID = memberID;
		firePropertyChange("memberID", oldmemberID, this.memberID);
	}

	public Long getLoanSequenceID() {
		return loanSequenceID;
	}

	public void setLoanSequenceID(Long loanSequenceID) {
		Object oldloanSequenceID = this.loanSequenceID;
		this.loanSequenceID = loanSequenceID;
		firePropertyChange("loanSequenceID", oldloanSequenceID, this.loanSequenceID);
	}

	public Long getEntrySequenceID() {
		return entrySequenceID;
	}

	public void setEntrySequenceID(Long entrySequenceID) {
		Object oldentrySequenceID = this.entrySequenceID;
		this.entrySequenceID = entrySequenceID;
		firePropertyChange("entrySequenceID", oldentrySequenceID,
				this.entrySequenceID);
	}

	public BigDecimal getAmount() {
		return amount;
	}

	public void setAmount(BigDecimal amount) {
		Object oldamount = this.amount;
		this.amount = amount;
		firePropertyChange("amount", oldamount, this.amount);
	}

	public Date getInsertStamp() {
		return insertStamp;
	}

	public void setInsertStamp(Date insertStamp) {
		Object oldinsertStamp = this.insertStamp;
		this.insertStamp = insertStamp;
		firePropertyChange("insertStamp", oldinsertStamp, this.insertStamp); 
	}
	
	public String createDateString() {
		if (getMemberToLoan() == null || getMemberToLoan().getStartDate() == null) {
			return "";
		}
		if (getStartDate() == null) {
			return "";
		}
		Calendar c = Calendar.getInstance();
		c.setTime(getStartDate());
		
		StringBuilder builder = new StringBuilder(32);
		builder.append("<html>");
		builder.append(c.get(Calendar.YEAR));
		builder.append(" CW ");
		builder.append(c.get(Calendar.WEEK_OF_YEAR));
		builder.append(" [<small>");
		builder.append(DateFormat.getDateInstance(DateFormat.DEFAULT).format(getStartDate()));
		builder.append(" - ");
		
		builder.append(DateFormat.getDateInstance(DateFormat.DEFAULT).format(getEndDate()));
		builder.append("]</small>");
		
		return builder.toString();
	}
		
}
